package com.njtoyo.taxi.admin.rest.controller.business.ride;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.format.DatePrinter;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.hutool.poi.excel.StyleSet;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.njtoyo.taxi.admin.aop.PassToken;
import com.njtoyo.taxi.admin.aop.PermissionScope;
import com.njtoyo.taxi.admin.mapper.master.entity.OrderManageAllVo;
import com.njtoyo.taxi.admin.mapper.master.entity.OrderManageVo;
import com.njtoyo.taxi.admin.mapper.master.entity.SimpleCall;
import com.njtoyo.taxi.admin.mapper.master.enums.RideCategory;
import com.njtoyo.taxi.admin.mapper.master.enums.RideStateState;
import com.njtoyo.taxi.admin.rest.export.RideExportPresenter;
import com.njtoyo.taxi.admin.rest.export.simple_call.SimpleCallRideExportPresenter;
import com.njtoyo.taxi.admin.rest.presenter.business.ride.RideDetailPresenter;
import com.njtoyo.taxi.admin.rest.presenter.business.ride.RideDialListPresenter;
import com.njtoyo.taxi.admin.rest.presenter.business.ride.RideListPresenter;
import com.njtoyo.taxi.admin.rest.presenter.business.ride.RideTrackPresenter;
import com.njtoyo.taxi.admin.rest.wrapper.business.ride.*;
import com.njtoyo.taxi.admin.rest.wrapper.business.simpleCallRide.SimpleCallRideQueryWrapper;
import com.njtoyo.taxi.admin.service.business.ride.RideService;
import com.njtoyo.taxi.entity.backend.AdminUser;
import com.taxi.entity.common.RestResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.ss.usermodel.CellStyle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;

@RestController
@Api(value = "行程", tags = "行程")
@RequestMapping("business/ride")
public class RideController {

    @Autowired
    private RideService rideService;

    @GetMapping("/{id}/dial")
    @ApiOperation(value = "隐私通话记录", notes = "权限：ride_online_dial")
    @PermissionScope(names = {"ride_online_dial"})
    RestResult<List<RideDialListPresenter>> dial(@ModelAttribute("admin") AdminUser adminUser, @PathVariable("id") Long id) {
        return rideService.getDialList(adminUser, id);
    }

    @GetMapping()
    @ApiOperation(value = "行程列表", notes = "权限：ride_online_list")
    @PermissionScope(names = {"ride_online_list"})
    RestResult<IPage<RideListPresenter>> getRideList(@ModelAttribute("admin") AdminUser adminUser, RideQueryWrapper wrapper) {
        return rideService.getList(adminUser, wrapper);
    }


    @GetMapping("/export")
    @ApiOperation(value = "行程列表-导出")
    void rideListExport(@ApiIgnore @ModelAttribute("admin") AdminUser adminUser, RideQueryWrapper wrapper, HttpServletResponse response) throws IOException {
        wrapper.setSize(100000);
        RestResult<IPage<RideListPresenter>> result = rideService.getList(adminUser, wrapper);
        IPage<RideListPresenter> page = result.getData();
        List<Map<String, Object>> rows = new ArrayList<>();
        for (RideListPresenter ride : page.getRecords()) {
            Map<String, Object> row = new HashMap<>();
            row.put("平台/类型/订单号", StrUtil.format("{}-{}-{}", ride.getPlatform().getDesc(), ride.getCategory().getDesc(), ride.getId()));
            row.put("公司名称", ride.getCompany().getName());
            row.put("司机编号", ride.getDriver().getId());
            row.put("司机名称", ride.getDriver().getName());
            row.put("司机电话", ride.getDriver().getMobileNumber());
            row.put("车牌号", ride.getTaxi().getPlateNumber());
            row.put("乘客编号", ride.getUser().getId());
            row.put("乘客名称", ride.getUser().getName());
            row.put("乘客电话", ride.getUser().getMobileNumber());
            row.put("下单时间", ObjectUtil.isNotNull(ride.getCreatedAt()) ? DateUtil.format(ride.getCreatedAt(), DatePattern.NORM_DATETIME_PATTERN) : "");
            row.put("行政区", ObjectUtil.isNull(ride.getArea()) ? "" : ride.getArea().getName());
            row.put("预约上下车信息", "起点:" + ride.getCallOriginName() + "\n终点:" + ride.getCallDestinationName());
            row.put("实际上下车信息", "起点:" + (StrUtil.isBlank(ride.getOriginName()) ? ride.getCallOriginName() : ride.getOriginName()) +
                    "\n终点:" + (StrUtil.isBlank(ride.getDestinationName()) ? ride.getCallDestinationName() : ride.getDestinationName()));
            if (ObjectUtil.isNotNull(ride.getRideOrder())) {
                row.put("支付信息", "金额:" + ride.getRideOrder().getAmount() + "\n " +
                        "支付方式:" + (ObjectUtil.isNull(ride.getRideOrder().getPaidThrough()) ? "" : ride.getRideOrder().getPaidThrough().getDesc()) + "\n" +
                        "支付结果:" + (ObjectUtil.isNull(ride.getRideOrder().getState()) ? "" : ride.getRideOrder().getState().getDesc()));
            } else {
                row.put("支付信息", "");
            }
            row.put("支付金额", ObjectUtil.isNotNull(ride.getRideOrder()) ? ride.getRideOrder().getAmount() : "");
            if (ride.getCategory() == RideCategory.appointment) {
                if (ride.getState() == RideStateState.pickuping) {
                    row.put("订单状态", "司机已出发");
                } else {
                    row.put("订单状态", ride.getState().getDesc());
                }
            } else if (ride.getCategory() == RideCategory.realtime) {
                if (ride.getState() == RideStateState.pickuping) {
                    row.put("订单状态", "司机已接单");
                } else {
                    row.put("订单状态", ride.getState().getDesc());
                }
            } else {
                row.put("订单状态", ride.getState().getDesc());
            }

            rows.add(row);
        }
        ExcelWriter writer = ExcelUtil.getWriter();
        StyleSet style = writer.getStyleSet();
        CellStyle cellStyle = style.getHeadCellStyle();
        cellStyle.setWrapText(true);
        writer.write(rows, true);
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=ride_order.xls");
        ServletOutputStream out = response.getOutputStream();
        System.out.println();

        writer.flush(out, true);
        writer.close();
        IoUtil.close(out);
    }

    @GetMapping("/{id}")
    @ApiOperation(value = "行程详情", notes = "权限：ride_online_detail")
    @PermissionScope(names = {"ride_online_detail"})
    RestResult<RideDetailPresenter> getRideDetail(@PathVariable("id") Long id) {
        return rideService.getRideDetail(id);
    }

    @PatchMapping("/{id}/suspicious-confirm")
    @ApiOperation(value = "异常行程确认", notes = "权限：suspicious_ride_confirm")
    @PermissionScope(names = {"suspicious_ride_confirm"})
    RestResult<Boolean> suspiciousConfirm(@PathVariable("id") Long id, @Valid @RequestBody SuspiciousConfirmWrapper wrapper) {
        return rideService.suspiciousConfirm(id, wrapper);
    }

    @PatchMapping("/{id}/order/online-order-set-offline")
    @ApiOperation(value = "修改支付方式(线上改线下)", notes = "权限：set_online_order_to_offline")
    @PermissionScope(names = {"set_online_order_to_offline"})
    RestResult<Boolean> onlineOrderSetOffline(@ApiIgnore @ModelAttribute("admin") AdminUser adminUser, @PathVariable("id") Long id) {
        return rideService.onlineOrderSetOffline(adminUser,id);
    }

    @PatchMapping("/{id}/order/set-offline-order-to-online")
    @ApiOperation(value = "修改支付方式(线下改线上)", notes = "权限：set_offline_order_to_online")
    @PermissionScope(names = {"set_offline_order_to_online"})
    RestResult<Boolean> offlineOrderSetOnline(@PathVariable("id") Long id) {
        return rideService.offlineOrderSetOnline(id);
    }

    @PatchMapping("/{id}/cancellation/responsibility/driver/eliminate")
    @ApiOperation(value = "有责改无责(司机有责)", notes = "权限：eliminate_ride_driver_cancel_responsibility")
    @PermissionScope(names = {"eliminate_ride_driver_cancel_responsibility"})
    RestResult<Boolean> driverCancellationResponsibilityEliminate(@PathVariable("id") Long id) {
        return rideService.driverCancellationResponsibilityEliminate(id);
    }

    @PatchMapping("/{id}/state")
    @ApiOperation(value = "修改行程状态", notes = "权限：ride_set_state")
    @PermissionScope(names = {"ride_set_state"})
    RestResult<Boolean> updateState(@PathVariable("id") Long id, @Valid @RequestBody UpdateStateWrapper wrapper) {
        return rideService.updateState(id, wrapper);
    }

    @PatchMapping("/{id}/cancellation/responsibility/customer/eliminate")
    @ApiOperation(value = "有责改无责(乘客有责)-未支付空驶费订单", notes = "权限：eliminate_ride_customer_cancel_responsibility")
    @PermissionScope(names = {"eliminate_ride_customer_cancel_responsibility"})
    RestResult<Boolean> customerCancellationResponsibilityEliminate(@PathVariable("id") Long id) {
        return rideService.customerCancellationResponsibilityEliminate(id);
    }

    @PatchMapping("/{id}/order/update-amount")
    @ApiOperation(value = "修改未付款订单金额", notes = "权限：modify_unpaid_ride_order_amount")
    @PermissionScope(names = {"modify_unpaid_ride_order_amount"})
    RestResult<Boolean> updateOrderAmount(@PathVariable("id") Long id, @Valid @RequestBody UpdateOrderAmountWrapper wrapper) {
        return rideService.updateOrderAmount(id, wrapper);
    }

    @GetMapping("/{id}/track")
    @ApiOperation(value = "行程轨迹", notes = "权限：ride_track_log")
    @PermissionScope(names = {"ride_track_log"})
    RestResult<RideTrackPresenter> getTrack(@PathVariable("id") Long id) {
        return rideService.getTrack(id);
    }

    @PostMapping("/{id}/close-driver-automatic")
    @ApiOperation(value = "关闭司机自动抢单", notes = "权限：close_driver_automatic")
    @PermissionScope(names = {"close_driver_automatic"})
    RestResult<Boolean> closeDriverAutomatic(@PathVariable("id") Long id, @Valid @RequestBody CloseDriverAutomaticWrapper wrapper) {
        return rideService.closeDriverAutomatic(id, wrapper);
    }

    @PostMapping("/{id}/cancel")
    @ApiOperation(value = "取消", notes = "权限：ride_cancel")
    @PermissionScope(names = {"ride_cancel"})
    RestResult<Boolean> cancel(@PathVariable("id") Long id) {
        return rideService.cancel(id);
    }

    @PostMapping("/{id}/order/refund")
    @ApiOperation(value = "乘客行程order退款", notes = "权限：ride_refund_order")
    @PermissionScope(names = {"ride_refund_order"})
    RestResult<Boolean> orderRefund(@PathVariable("id") Long id) {
        return rideService.orderRefund(id);
    }

    @PostMapping("/{id}/cancellation/responsibility/customer/refund")
    @ApiOperation(value = "有责取消退款", notes = "权限：refund_cancellation_order")
    @PermissionScope(names = {"refund_cancellation_order"})
    RestResult<Boolean> CustomerCancellationResponsibilityEliminateRefund(@PathVariable("id") Long id) {
        return rideService.customerCancellationResponsibilityRefund(id);
    }


    @GetMapping("/{mobileNumber}/passengerInfo")
    RestResult<SimpleCall> passenger(@PathVariable("mobileNumber") String mobileNumber) {
        return rideService.passengerInfo(mobileNumber);
    }


    /**
     * 异常单
     *
     * @param adminUser
     * @param wrapper
     * @return
     */
    @GetMapping("/suspiciousPage")
    RestResult<IPage<RideListPresenter>> suspiciousPage(@ModelAttribute("admin") AdminUser adminUser, RideQueryWrapper wrapper) {
        return rideService.suspiciousPage(adminUser, wrapper);
    }


    @GetMapping("/export_suspicious")
    void exportSuspicious(@ApiIgnore @ModelAttribute("admin") AdminUser adminUser, RideQueryWrapper wrapper, HttpServletResponse response) throws IOException {
        wrapper.setSize(100000);
        RestResult<IPage<RideListPresenter>> result = rideService.suspiciousPage(adminUser, wrapper);
        IPage<RideListPresenter> page = result.getData();
        List<Map<String, Object>> rows = new ArrayList<>();
        for (RideListPresenter ride : page.getRecords()) {
            Map<String, Object> row = new HashMap<>();
            row.put("平台/类型/订单号", StrUtil.format("{}-{}-{}", ride.getPlatform().getDesc(), ride.getCategory().getDesc(), ride.getId()));
            row.put("司机编号", ride.getDriver().getId());
            row.put("司机名称", ride.getDriver().getName());
            row.put("司机电话", ride.getDriver().getMobileNumber());
            row.put("车牌号", ride.getTaxi().getPlateNumber());
            row.put("乘客编号", ride.getUser().getId());
            row.put("乘客名称", ride.getUser().getName());
            row.put("乘客电话", ride.getUser().getMobileNumber());
            row.put("扫码时间", ObjectUtil.isNotNull(ride.getCreatedAt()) ? DateUtil.format(ride.getCreatedAt(), DatePattern.NORM_DATETIME_PATTERN) : "");
            row.put("行政区", ObjectUtil.isNull(ride.getArea()) ? "" : ride.getArea().getName());
            row.put("预约上下车信息", "起点:" + ride.getCallOriginName() + "\n终点:" + ride.getCallDestinationName());
            row.put("实际上下车信息", "起点:" + ride.getOriginName() + "\n终点:" + ride.getDestinationName());
            if (ObjectUtil.isNotNull(ride.getRideOrder())) {
                row.put("支付信息", "金额:" + ride.getRideOrder().getAmount() + "\n " +
                        "支付方式:" + (ObjectUtil.isNull(ride.getRideOrder().getPaidThrough()) ? "" : ride.getRideOrder().getPaidThrough().getDesc()) + "\n" +
                        "支付结果:" + (ObjectUtil.isNull(ride.getRideOrder().getState()) ? "" : ride.getRideOrder().getState().getDesc()));
                row.put("支付金额", ObjectUtil.isNotNull(ride.getRideOrder().getAmount()) ? ride.getRideOrder().getAmount() : "");
            } else {
                row.put("支付信息", "");
            }
            row.put("订单状态", ride.getState().getDesc());
            rows.add(row);
        }
        ExcelWriter writer = ExcelUtil.getWriter();
        StyleSet style = writer.getStyleSet();
        CellStyle cellStyle = style.getHeadCellStyle();
        cellStyle.setWrapText(true);
        writer.write(rows, true);
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=ride_order.xls");
        ServletOutputStream out = response.getOutputStream();

        writer.flush(out, true);
        writer.close();
        IoUtil.close(out);
    }


    /**
     * @param rideId
     * @return
     */
    @GetMapping("/{rideId}/privacyCallLog")
    RestResult callLog(@PathVariable("rideId") Long rideId) {
        return rideService.privacyCallLogByRideId(rideId);
    }

    @GetMapping("/{subscriptionId}/privacyCallDetailLog")
    RestResult privacyCallDetailLog(@PathVariable("subscriptionId") String subscriptionId) {
        return rideService.privacyCallDetailLog(subscriptionId);
    }


    @GetMapping("/willRefundDetail/{id}")
    RestResult willRefundDetail(@PathVariable("id") Long id) {
        return rideService.willRefundDetail(id);
    }

    @GetMapping("/getRefundCount")
    RestResult getRefundCount(@RequestParam(value = "callId") Long callId,
                              @RequestParam(value = "callCategory") Integer callCategory) {
        return rideService.getRefundCount(callId, callCategory);
    }

    @PostMapping("/finishOrder/{rideId}")
    RestResult finishOrder(@PathVariable("rideId") Long rideId) {
        return rideService.finishOrder(rideId);
    }

    @PostMapping("/createOrderBill")
    RestResult createOrderBill(@ModelAttribute("admin") AdminUser adminUser, @RequestBody Dict dict) {
        Integer rideId = dict.getInt("rideId");
        BigDecimal taxiAmount = dict.getBigDecimal("taxiAmount");
        BigDecimal tollAmount = dict.getBigDecimal("tollAmount");
        BigDecimal otherAmount = dict.getBigDecimal("otherAmount");
        return rideService.createOrderBill(rideId, taxiAmount, tollAmount, otherAmount);
    }


    @PostMapping("/order/refund-new")
    @ApiOperation(value = "乘客行程order退款", notes = "权限：ride_refund_order")
    @PermissionScope(names = {"ride_refund_order"})
    RestResult<Boolean> orderRefundNew(@ModelAttribute("admin") AdminUser adminUser, @RequestBody Dict dict) {
        Long rideId = dict.getLong("rideId");
        BigDecimal refundAmount = dict.getBigDecimal("refundAmount");
        String refundType = dict.getStr("refundType");
        String reason = dict.getStr("reason");
        if (ObjectUtil.isNull(rideId)) {
            return RestResult.failed("参数错误:缺少必要参数[rideId]");
        }
        if (StrUtil.isBlank(refundType)) {
            return RestResult.failed("请选择退款类型");
        } else if ("PART".equals(refundType) && ObjectUtil.isNull(refundAmount)) {
            return RestResult.failed("请输入退款金额");
        }
        if (StrUtil.isBlank(reason)) {
            return RestResult.failed("请输入退款原因");
        }
        return rideService.orderRefundNew(adminUser, rideId, refundAmount, refundType, reason);
    }

    @GetMapping("/getOrderManageAll")
    @ApiOperation(value = "业务管理-订单管理查询全部")
    RestResult<OrderManageAllVo> getOrderListAll(@ModelAttribute("admin") AdminUser adminUser, OrderManageQueryDto queryDto) {
        OrderManageAllVo all = rideService.getAll(adminUser, queryDto);
        return RestResult.success(all);
    }


    @GetMapping("/refundListByRideId/{rideId}")
    RestResult refundListByRideId(@PathVariable("rideId") Long rideId) {
        return rideService.refundListByRideId(rideId);
    }

}
